#include "Log.hpp"
#include "Socket.hpp"
#include<sys/select.h>
#include<sys/poll.h>

#define MAX_FD_NUM 1024
class PollServer
{
    const static int DefaultFD = -1;

public:
    PollServer(uint16_t port,int num) : _port(port), _listensockfd(std::make_unique<TcpSocket>()),_num(num)
    {
        _listensockfd->BuildListenSocket(port);
    }
    void Init()
    {
        _pfds=new struct pollfd[_num];
        for(int i=0;i<_num;i++)
        {
            _pfds[i].fd=DefaultFD;
            _pfds[i].events=0;
            _pfds[i].revents=0;
        }
        _pfds[0].fd=_listensockfd->Sockfd();
        _pfds[0].events|=POLLIN;
    }
    void Acceptor()
    {
        struct sockaddr_in addr;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(_port);
        socklen_t len;
        int sock = ::accept(_listensockfd->Sockfd(), (struct sockaddr *)&addr, &len);
        if (sock < 0)
        {
            LOG(ERROR, "accept failed!\n");
            return;
        }
        int pos = 0;
        for (; pos < _num; pos++)
        {
            if (_pfds[pos].fd == DefaultFD)
                break;
        }
        if (pos == _num)
        {
            LOG(ERROR, "select 监控位置已满  需要扩容! \n");
            close(sock);
            //xxxxxxxxxxxxxxxxxxx
            return;
        }
        _pfds[pos].fd=sock;
        _pfds[pos].events|=POLLIN;
    }
    void HandlerIO(int pos)
    {
        char buffer[4096];
        int fd=_pfds[pos].fd;
        ssize_t n = ::recv(fd, buffer, sizeof(buffer)-1,0);
        if (n == 0)
        {
            LOG(DEBUG, "write close!\n");
            fd = DefaultFD;
            close(fd);
        }
        if (n == -1)
        {
            LOG(ERROR, "read error!\n");
            close(fd);
            fd = DefaultFD;
        }
        else
        {
            buffer[n] = 0;
            std::cout << "Client say# " << buffer << std::endl;
            std::string content = "<html><body><h1>hello Linux</h1></body></html>";
            std::string echo_str = "HTTP/1.0 200 OK\r\n";
            echo_str += "Content-Type: text/html\r\n";
            echo_str += "Content-Length: " + std::to_string(content.size()) + "\r\n\r\n";
            echo_str += content;
            send(fd, echo_str.c_str(), echo_str.size(),0);
        }
    }
    void HandleEvent()
    {

        for (int i = 0; i < _num; i++)
        {
            if (_pfds[i].fd==DefaultFD)
                continue;
            if (_pfds[i].events&=POLLIN)
            {
                if(_pfds[i].fd == _listensockfd->Sockfd())
                Acceptor();
                else 
                HandlerIO(i);
            }
            else
            {
                LOG(ERROR,"poll handle error!\n");
            }
        }
    }
    void Loop()
    {
        LOG(INFO, "开始循环\n");
        while (1)
        {
            int n = ::poll(_pfds,_num,-1);
            switch (n)
            {
            case 0:
                LOG(DEBUG, "time out ! \n");
                break;
            case -1:
                LOG(ERROR, "select error !\n");
                break;
            default:
                HandleEvent(); // 如果不处理，select会一直提醒
                sleep(1);
                break;
            }
        }
    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensockfd;
    int arr_fd[MAX_FD_NUM] ;
    int _num;
    struct pollfd* _pfds;
};